#coding=utf-8
#auth:beck shen
#date:2017-11-09


from pytw.tools import log
from pytw.core.tasklet import Tasklet

from twisted.enterprise import adbapi
from twisted.internet import reactor, threads


class _ConnectionPool(adbapi.ConnectionPool):

    """
    数据库连接池
    """

    reconnect = True

    def connect(self):
        try:
            conn = adbapi.ConnectionPool.connect(self)
            return conn
        except Exception as e:
            raise adbapi.ConnectionLost(e.message)

    def _runWithConnection(self, func, *args, **kw):
        """
        rollback失败抛出异常,方便数据重写
        """
        conn = self.connectionFactory(self)
        try:
            result = func(conn, *args, **kw)
            conn.commit()
            return result
        except:
            excType, excValue, excTraceback = sys.exc_info()
            conn.rollback()
            compat.reraise(excValue, excTraceback) 

    def keep_alive(self):
        """
        心跳包，主要解决mysql在8小时自动断开问题
        """
        for i in range(self.max):
            try:
                self.query(self.good_sql)
            except Exception as e:
                log.err("keep_alive_failed!", e.message)

class ConnectionPool(_ConnectionPool):

    """
    stackless中使用的连接池
    """
    
    def query(self, *args, **kwargs):
        """
        存在返回结果集的sql
        """
        d = self.runQuery(*args, **kwargs)
        result = Tasklet.current.get_result(d)
        return result
        
    def operation(self, *args, **kwargs):
        """
        不存在返回结果集
        """
        d = self.runOperation(*args, **kwargs)
        result = Tasklet.current.get_result(d)
        return result
    

class FlaskConnectionPool(_ConnectionPool):

    """
    纯twisted运行的连接池，仅仅在线程
    中运行时，才使用query函数，主要解决twisted.web.wsgi
    在线程中运行，等待数据库返回结果
    """
   
    def query(self, *args, **kwargs):
        result = threads.blockingCallFromThread(
            reactor, self.runQuery, *args, **kwargs
        )
        return result

    def operation(self, *args, **kwargs):
        result = threads.blockingCallFromThread(
            reactor, self.runOperation, *args, **kwargs 
        )
        return result

    def keep_alive(self):
        """
        心跳检查
        """
        for i in range(self.max):
            try:
                self.runQuery(self.good_sql)
            except Exception as e:
                log.err("keep_alive_failed!", e.message)        
